<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue MVVM模式的简单实现_原始版</title>
</head>
<body>
<h3>Vue mvvm simple model</h3>
<div id="app">
  <h2 v-text="title"></h2>
  <p v-text="message"></p>
  <input v-model="message">
  <button v-on:click="resetInput()">重置数据</button>
</div>


<script>
  function Vue(opt) {
    var self = this;

    var root = document.querySelector(opt.el || 'body');

    var regNewline = /\n/g;
    var regText = /\{\{(.+?)\}\}/g;
    var regDir = /^v-(\w+)\:?(\w+)\=\"(\w+)\"$/g;

    this.$data = opt.data;
    this.data = {};
    this.methods = opt.methods;

    // 遍历root内元素
    function parseHtml(node) {
      var children = node.children;
      for (var i = 0, l = children.length; i < l; i++) {
        var child = children[i];
        if (child.children.length !== 0) {
          parseHtml(child);
        }
        parseAttr(child);
      }
    }

    // 解析指令
    function parseAttr(node) {
      var attrs = node.attributes;
      for (var i = 0, l = attrs.length; i < l; i++) {
        switch (regDir.exec(attrs[i])) {
          case 'v-bind':
            updateData(node, attrs[i]);
            break;
          case 'v-model':
            bindModel(node, attrs[i]);
            break;
          case 'v-on:click':
            bindEvent(node, attrs[i]);
            break;
          default :
            return null;
        }
      }
    }

    // 双向绑定model
    function bindModel(node, model) {
      node.addEventListener('keyup', function () {
        self.data[model] = node.value;
      });
    }

    // 绑定事件
    function bindEvent(node, method) {
      node.addEventListener('click', function () {
        self.methods[method].call(self);
      });
    }

    // 展示数据
    function updateData(node, data) {
      node.textContent = self.data[data];
    }

    //        // 编译单个节点的 {{}}
    //        function compileText(node) {
    //            var text = node.textContent.trim().replace(regNewline, '');
    //            var pieces = text.split(regText);
    //            var matches = text.match(regText);
    //            var tokens = [];
    //
    //            if (!pieces.length) {
    //                return;
    //            }
    //
    //            // 文本节点转化为常量和变量的组合表达式
    //            // 'a {{b}} c' => '"a " + b + " c"'
    //            pieces.forEach(function (piece) {
    //                if (matches.indexOf('{{' + piece + '}}') > -1) {
    //                    tokens.push(piece.trim());
    //                } else if (piece) {
    //                    tokens.push('"' + piece + '"');
    //                }
    //            });
    //
    //            with (self.$data) {
    //                var res = eval(tokens.join('+'));
    //            }
    //            node.textContent = res;
    //        }

    // 通知更新
    function notify() {

    }

    // 下面只定义了data这一层的setter、getter
    function observeInit() {

      var data = self.data;
      for (var key in self.$data) {

        Object.defineProperty(data, key, {
          get: function () {
            console.log('getter');
            return self.$data[key];
          },
          set: function (newValue) {
            console.log('setter');
            if (self.$data[key] === newValue) {
              return;
            }
            self.$data[key] = newValue;
            notify();
          }
        });
      }
    }

    observeInit();

    //        parseHtml(root);
  }

  // parseHtml => compile(directive) => update => defineProperty => update


  var vm = new Vue({
    el: '#app',
    data: {
      message: 'message',
      title: 'Hello Vue!'
    },
    methods: {
      resetInput: function () {
        this.data.input = 'reset message';
      }
    }
  });
</script>
</body>
</html>